package com.erdos.message.command;

import java.io.Serializable;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.omg.IOP.ServiceContext;

import com.erdos.common.service.AppServiceHelper;
import com.erdos.message.entity.MessageHandlerMapping;
import com.erdos.message.vo.MessageProvider;

public class EventProcessServiceInvocation implements ServiceInvocation {
	private static final long serialVersionUID = 5050692831272732266L;
	private static final Log logger=LogFactory.getLog(EventProcessServiceInvocation.class);
	
	private MessageHandlerMappingService msgHandlerMappingService;
	private ProcessFacade processFacade;
	
	/* (non-Javadoc)
	 * @see com.hp.message.command.ServiceInvocation#execute(java.lang.String, java.lang.Object)
	 */
	/**
	 * looks for the event id through the msgTypeId, and calls the ProcessFacade to start the process.
	 * the parameter key in ServiceContext is: VALUE_OBJECT
	 */
	public Serializable execute(String msgTypeId, Object entity) throws ServiceInvocationException {
		if(logger.isDebugEnabled()) {
			logger.debug("EventProcessServiceInvocation: msgTypeId=" + msgTypeId + ", entity=" + entity);
		}
		
		if(msgHandlerMappingService==null){
			msgHandlerMappingService = (MessageHandlerMappingService)AppServiceHelper.findBean("messageHandlerMappingService");
		}
		
		MessageHandlerMapping mapping=this.msgHandlerMappingService.findByMsgTypeId(msgTypeId);
		if(mapping==null) {
			logger.error("processing received message, no message type handler configured for  " + msgTypeId);
			throw new ServiceInvocationException("no message type handler configured for message type " + msgTypeId);
		}
		
		String eventId=mapping.getEventId();
		if(StringUtils.isBlank(eventId)) {
			logger.error("processing received message, event Id is not configured for message type " + msgTypeId);
			throw new ServiceInvocationException("Illegal configuration for handler, event id is blank. message type id=" + msgTypeId);
		}
		
		final ServiceContext context=new ServiceContext();
		context.setAttribute(ServiceContext.EVENT_ID, eventId);
		context.setAttribute(ServiceContext.VALUE_OBJECT, entity);
		if(entity instanceof MessageProvider) {
			context.setAttribute(ServiceContext.MESSAGE_ID, ((MessageProvider)entity).getMessageId());
		}		
		
		try {
			if(processFacade==null){
				processFacade =(ProcessFacade)AppServiceHelper.findBean("processFacade"); 
			}
			this.processFacade.doStartProcess(context);
		} catch (ProcessException ex) {
			final String errMsg="msgTypeId:" + msgTypeId + ", eventId:" + eventId + ",parameter:" + entity;
			logger.error(errMsg, ex);
			throw new ServiceInvocationException(errMsg, ex);
		} 
		
		if(logger.isDebugEnabled()) {
			logger.debug("EventProcessServiceInvocation: event Id=" + eventId);
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see com.hp.message.Messaging#getMessageTypeId()
	 */
	/**
	 * since this implementation find the Event Id through messageTypeId, and then 
	 * locate the Process class by event Id, this instance does not map to a dedicated messageTypeId.
	 * this method always returns null.
	 */
	public String getMessageTypeId() {
		return null;
	}

	/**
	 * @param msgHandlerMappingService the msgHandlerMappingService to set
	 */
	public void setMsgHandlerMappingService(MessageHandlerMappingService msgHandlerMappingService) {
		this.msgHandlerMappingService = msgHandlerMappingService;
	}

	/**
	 * @param processFacade the processFacade to set
	 */
	public void setProcessFacade(ProcessFacade processFacade) {
		this.processFacade = processFacade;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1317;
		result = prime * result ;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
			
		if (obj == null) {
			return false;
		}
			
		if (!(obj.getClass().equals(EventProcessServiceInvocation.class))) {
			return false;
		}			

		return true;
	}

	/**
	 * @return the processFacade
	 */
	public ProcessFacade getProcessFacade() {
	    return processFacade;
	}

	/**
	 * @return the msgHandlerMappingService
	 */
	public MessageHandlerMappingService getMsgHandlerMappingService() {
	    return msgHandlerMappingService;
	}	
	
}
